package com.campus.secondhand.service.impl;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.campus.secondhand.service.CategoryService;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.secondhand.common.Result;
import com.campus.secondhand.entity.PurchaseRequest;
import com.campus.secondhand.entity.User;
import com.campus.secondhand.mapper.PurchaseRequestMapper;
import com.campus.secondhand.model.dto.PurchaseRequestCreateDTO;
import com.campus.secondhand.model.dto.PurchaseRequestStatusDTO;
import com.campus.secondhand.model.dto.PurchaseRequestUpdateDTO;
import com.campus.secondhand.model.vo.PurchaseRequestDetailVO;
import com.campus.secondhand.model.vo.PurchaseRequestVO;
import com.campus.secondhand.model.vo.UserDetailVO;
import com.campus.secondhand.model.vo.UserSimpleVO;
import com.campus.secondhand.service.PurchaseRequestService;
import com.campus.secondhand.service.SchoolService;
import com.campus.secondhand.service.UserService;
import com.campus.secondhand.service.MessageService;
import com.campus.secondhand.model.dto.MessageSendDTO;
import com.campus.secondhand.model.vo.ConversationVO;
import com.campus.secondhand.model.vo.MessageVO;
import com.campus.secondhand.service.FavoriteService;

import cn.hutool.core.bean.BeanUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;

/**
 * 求购信息服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PurchaseRequestServiceImpl extends ServiceImpl<PurchaseRequestMapper, PurchaseRequest>
        implements PurchaseRequestService {
    private final CategoryService categoryService;
    private final UserService userService;
    private final SchoolService schoolService;
    @Lazy
    private final MessageService messageService;
    private final FavoriteService favoriteService;
    private final RedisTemplate<String, Object> redisTemplate;

    // Redis缓存键常量
    private static final String CACHE_PURCHASE_DETAIL = "purchase:detail:";
    private static final String CACHE_PURCHASE_LIST = "purchase:list";
    private static final String CACHE_PURCHASE_USER = "purchase:list:user:";
    private static final String CACHE_PURCHASE_SCHOOL = "purchase:school:";
    private static final long CACHE_EXPIRATION = 12; // 缓存过期时间，单位小时

    @Override
    public Result<org.springframework.data.domain.Page<PurchaseRequestVO>> getRequestList(Double minBudget,
            Double maxBudget,
            List<String> categories, Long schoolId, String keyword, Pageable pageable, Long currentUserId) {

        // 构建缓存Key，不包含查询参数，便于后续删除操作
        StringBuilder cacheKeyBuilder = new StringBuilder(CACHE_PURCHASE_LIST);

        // 用户特定的结果（如是否收藏）应该有独立的缓存
        String cacheKey = cacheKeyBuilder.toString();
        if (currentUserId != null) {
            cacheKey += ":user:" + currentUserId;
        }

        // 尝试从缓存获取
        Object cachedResult = redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            try {
                // 将缓存的Map数据转换回Page对象
                java.util.Map<String, Object> pageData = (java.util.Map<String, Object>) cachedResult;
                java.util.List<PurchaseRequestVO> content = (java.util.List<PurchaseRequestVO>) pageData.get("content");
                long totalElements = ((Number) pageData.get("totalElements")).longValue();
                int number = ((Number) pageData.get("number")).intValue();
                int size = ((Number) pageData.get("size")).intValue();

                org.springframework.data.domain.Page<PurchaseRequestVO> pageResult = new PageImpl<>(
                        content, org.springframework.data.domain.PageRequest.of(number, size), totalElements);

                return Result.success(pageResult, "获取成功(缓存)");
            } catch (Exception e) {
                log.warn("缓存数据反序列化失败", e);
                // 缓存数据有问题，继续查询数据库
            }
        }

        LambdaQueryWrapper<PurchaseRequest> queryWrapper = Wrappers.lambdaQuery(PurchaseRequest.class);

        // 添加筛选条件
        if (minBudget != null) {
            queryWrapper.ge(PurchaseRequest::getBudget, minBudget);
        }

        if (maxBudget != null) {
            queryWrapper.le(PurchaseRequest::getBudget, maxBudget);
        }

        if (categories != null && !categories.isEmpty()) {
            queryWrapper.in(PurchaseRequest::getCategoryId, categories);
        }

        if (schoolId != null) {
            queryWrapper.eq(PurchaseRequest::getSchoolId, schoolId);
        }

        if (keyword != null && !keyword.trim().isEmpty()) {
            queryWrapper.and(wrapper -> wrapper
                    .like(PurchaseRequest::getTitle, keyword)
                    .or()
                    .like(PurchaseRequest::getDescription, keyword));
        }

        // 只查询有效状态的记录
        queryWrapper.eq(PurchaseRequest::getIsActive, 1);

        // 设置排序
        switch (pageable.getSort().toString()) {
            case "budget: ASC":
                queryWrapper.orderByAsc(PurchaseRequest::getBudget);
                break;
            case "budget: DESC":
                queryWrapper.orderByDesc(PurchaseRequest::getBudget);
                break;
            case "views: DESC":
                queryWrapper.orderByDesc(PurchaseRequest::getViews);
                break;
            case "createTime: DESC":
            default:
                queryWrapper.orderByDesc(PurchaseRequest::getCreateTime);
                break;
        }

        // 设置分页
        Page<PurchaseRequest> mybatisPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(
                pageable.getPageNumber() + 1, // MyBatis-Plus分页从1开始
                pageable.getPageSize());

        // 执行查询
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<PurchaseRequest> requestPage = this.page(mybatisPage,
                queryWrapper);

        // 转换为VO
        List<PurchaseRequestVO> voList = new ArrayList<>();
        for (PurchaseRequest request : requestPage.getRecords()) {
            PurchaseRequestVO vo = convertToVO(request);

            // 如果提供了当前用户ID，检查该用户是否已收藏此求购信息
            if (currentUserId != null) {
                // 使用FavoriteService检查是否收藏
                vo.setIsFavorite(favoriteService.isPurchaseRequestFavorite(currentUserId, request.getId()));
            } else {
                vo.setIsFavorite(false); // 默认为未收藏
            }

            voList.add(vo);
        }

        // 创建Spring Data的Page对象
        org.springframework.data.domain.Page<PurchaseRequestVO> resultPage = new PageImpl<>(
                voList, pageable, requestPage.getTotal());

        // 写入缓存（设置较短的过期时间）
        // 创建包含分页信息的Map而不是直接缓存PageImpl对象
        java.util.Map<String, Object> pageData = new java.util.HashMap<>();
        pageData.put("content", voList);
        pageData.put("totalElements", requestPage.getTotal());
        pageData.put("number", pageable.getPageNumber());
        pageData.put("size", pageable.getPageSize());

        redisTemplate.opsForValue().set(cacheKey, pageData, 1, TimeUnit.HOURS);

        return Result.success(resultPage, "获取成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> createRequest(Long userId, PurchaseRequestCreateDTO createDTO) {
        // 获取用户信息
        User user = userService.getUserById(userId);
        if (user == null) {
            return Result.error(404, "用户不存在");
        }

        // 创建求购信息
        PurchaseRequest request = new PurchaseRequest();
        request.setTitle(createDTO.getTitle());
        request.setDescription(createDTO.getDescription());
        request.setBudget(createDTO.getBudget());
        request.setCategoryId(createDTO.getCategoryId());
        request.setUserId(userId);
        request.setSchoolId(createDTO.getSchoolId());
        request.setCreateTime(LocalDateTime.now());
        request.setContactInfo(createDTO.getContactInfo());
        request.setUpdateTime(LocalDateTime.now());
        request.setExpireTime(createDTO.getExpireTime());
        request.setViews(0);
        request.setIsActive(1);
        request.setStatus(1); // 默认状态为1

        this.save(request);

        // 清除相关缓存
        clearPurchaseListCache();
        clearUserPurchaseCache(userId);

        if (user.getSchoolId() != null) {
            clearSchoolPurchaseCache(user.getSchoolId());
        }

        // 构建响应
        return Result.success(
                PurchaseRequestDetailVO.builder()
                        .id(request.getId())
                        .title(request.getTitle())
                        .createTime(request.getCreateTime())
                        .build(),
                "求购信息发布成功");
    }

    @Override
    public Result<PurchaseRequestDetailVO> getRequestDetail(Long id) {
        // 尝试从缓存获取
        String cacheKey = CACHE_PURCHASE_DETAIL + id;
        Object cachedDetail = redisTemplate.opsForValue().get(cacheKey);
        if (cachedDetail != null) {
            return Result.success((PurchaseRequestDetailVO) cachedDetail, "获取成功(缓存)");
        }

        PurchaseRequest request = this.getById(id);
        if (request == null) {
            return Result.error(404, "求购信息不存在");
        }

        PurchaseRequestDetailVO detailVO = convertToDetailVO(request);

        // 写入缓存
        redisTemplate.opsForValue().set(cacheKey, detailVO, CACHE_EXPIRATION, TimeUnit.HOURS);

        return Result.success(detailVO, "获取成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> updateRequestStatus(Long id, Long userId, PurchaseRequestStatusDTO statusDTO) {
        PurchaseRequest request = this.getById(id);
        if (request == null) {
            return Result.error(404, "求购信息不存在");
        }

        // 检查是否为发布者
        if (!request.getUserId().equals(userId)) {
            return Result.error(403, "无权限修改");
        }

        // 更新状态，将字符串状态转为整数
        Integer statusCode;
        switch (statusDTO.getStatus()) {
            case "COMPLETED":
                statusCode = 2;
                break;
            case "CANCELLED":
                statusCode = 3;
                break;
            case "PENDING":
            default:
                statusCode = 1;
                break;
        }

        request.setStatus(statusCode);
        request.setUpdateTime(LocalDateTime.now());
        this.updateById(request);

        // 清除缓存
        clearPurchaseCache(id);
        clearPurchaseListCache();
        clearUserPurchaseCache(userId);
        if (request.getSchoolId() != null) {
            clearSchoolPurchaseCache(request.getSchoolId());
        }

        return Result.success(null, "状态更新成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> deleteRequest(Long id, Long userId) {
        PurchaseRequest request = this.getById(id);
        if (request == null) {
            return Result.error(404, "求购信息不存在");
        }

        // 检查是否为发布者
        if (!request.getUserId().equals(userId)) {
            return Result.error(403, "无权限删除");
        }

        // 逻辑删除
        request.setIsActive(0);
        request.setUpdateTime(LocalDateTime.now());
        this.updateById(request);

        // 清除缓存
        clearPurchaseCache(id);
        clearPurchaseListCache();
        clearUserPurchaseCache(userId);
        if (request.getSchoolId() != null) {
            clearSchoolPurchaseCache(request.getSchoolId());
        }

        return Result.success(null, "删除成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> updateRequest(Long id, Long userId, PurchaseRequestUpdateDTO updateDTO) {
        PurchaseRequest request = this.getById(id);
        if (request == null) {
            return Result.error(404, "求购信息不存在");
        }

        // 检查是否为发布者
        if (!request.getUserId().equals(userId)) {
            return Result.error(403, "无权限修改");
        }

        BeanUtil.copyProperties(updateDTO, request);
        request.setUpdateTime(LocalDateTime.now());
        this.updateById(request);

        // 清除缓存
        clearPurchaseCache(id);
        clearPurchaseListCache();
        clearUserPurchaseCache(userId);
        if (request.getSchoolId() != null) {
            clearSchoolPurchaseCache(request.getSchoolId());
        }

        return Result.success(null, "更新成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> increaseViews(Long id) {
        PurchaseRequest request = this.getById(id);
        if (request == null) {
            return Result.error(404, "求购信息不存在");
        }

        // 增加浏览量
        request.setViews(request.getViews() + 1);
        request.setUpdateTime(LocalDateTime.now());
        this.updateById(request);

        // 更新缓存中的详情数据
        String cacheKey = CACHE_PURCHASE_DETAIL + id;
        redisTemplate.delete(cacheKey);

        return Result.success(null, "浏览量+1");
    }

    @Override
    public Result<org.springframework.data.domain.Page<PurchaseRequestVO>> getUserRequests(Long userId,
            Pageable pageable) {
        // 构建缓存Key，简化缓存标识符以便于删除
        String cacheKey = CACHE_PURCHASE_USER + userId;

        // 尝试从缓存获取
        Object cachedResult = redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            return Result.success((org.springframework.data.domain.Page<PurchaseRequestVO>) cachedResult, "获取成功(缓存)");
        }

        // 查询条件：用户ID + 有效状态
        LambdaQueryWrapper<PurchaseRequest> queryWrapper = Wrappers.lambdaQuery(PurchaseRequest.class)
                .eq(PurchaseRequest::getUserId, userId)
                .eq(PurchaseRequest::getIsActive, 1)
                .orderByDesc(PurchaseRequest::getCreateTime);

        // 设置分页
        Page<PurchaseRequest> mybatisPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(
                pageable.getPageNumber() + 1,
                pageable.getPageSize());

        // 执行查询
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<PurchaseRequest> requestPage = this.page(mybatisPage,
                queryWrapper);

        // 转换为VO
        List<PurchaseRequestVO> voList = requestPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(java.util.stream.Collectors.toList());

        // 创建Spring Data的Page对象
        org.springframework.data.domain.Page<PurchaseRequestVO> resultPage = new PageImpl<>(
                voList, pageable, requestPage.getTotal());

        // 写入缓存 - 使用Map存储分页数据
        java.util.Map<String, Object> pageData = new java.util.HashMap<>();
        pageData.put("content", voList);
        pageData.put("totalElements", requestPage.getTotal());
        pageData.put("number", pageable.getPageNumber());
        pageData.put("size", pageable.getPageSize());

        redisTemplate.opsForValue().set(cacheKey, pageData, 30, TimeUnit.MINUTES);

        return Result.success(resultPage, "获取成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> contactPublisher(Long id, Long userId, String message) {
        // 尝试从缓存获取求购信息
        String cacheKey = CACHE_PURCHASE_DETAIL + id;
        PurchaseRequestDetailVO cachedDetail = null;
        Object cachedObj = redisTemplate.opsForValue().get(cacheKey);
        if (cachedObj != null) {
            cachedDetail = (PurchaseRequestDetailVO) cachedObj;
        }

        // 如果缓存不存在，从数据库获取
        PurchaseRequest request;
        if (cachedDetail == null) {
            request = this.getById(id);
            if (request == null) {
                return Result.error(404, "求购信息不存在");
            }
        } else {
            // 使用缓存中的发布者ID
            request = new PurchaseRequest();
            request.setId(cachedDetail.getId());
            request.setUserId(cachedDetail.getUser().getId());
        }

        // 获取用户信息
        User user = userService.getUserById(userId);
        if (user == null) {
            return Result.error(404, "用户不存在");
        }

        // 获取发布者信息
        User publisher = userService.getUserById(request.getUserId());
        if (publisher == null) {
            return Result.error(404, "发布者不存在");
        }

        // 不能联系自己
        if (userId.equals(request.getUserId())) {
            return Result.error(400, "不能联系自己");
        }

        // 实现实际联系发布者的业务逻辑
        try {
            // 1. 创建或获取会话
            Long publisherId = request.getUserId();
            Result<ConversationVO> conversationResult = messageService.createConversation(userId, publisherId);
            if (conversationResult.getCode() != 200) {
                return Result.error(conversationResult.getCode(), "创建会话失败：" + conversationResult.getMessage());
            }

            // 2. 发送消息
            // 2.1 发送用户输入的消息
            MessageSendDTO userMessageDTO = new MessageSendDTO();
            userMessageDTO.setReceiverId(publisherId);
            userMessageDTO.setContent(message);
            userMessageDTO.setUserId(userId);

            Result<MessageVO> userMessageResult = messageService.sendMessage(userId, userMessageDTO);
            if (userMessageResult.getCode() != 200) {
                return Result.error(userMessageResult.getCode(), "发送用户消息失败：" + userMessageResult.getMessage());
            }

            // 2.2 发送求购信息引用消息
            MessageSendDTO requestReferenceDTO = new MessageSendDTO();
            requestReferenceDTO.setReceiverId(publisherId);
            requestReferenceDTO.setUserId(userId);
            requestReferenceDTO.setRequestId(id);

            Result<MessageVO> referenceResult = messageService.sendMessage(userId, requestReferenceDTO);
            if (referenceResult.getCode() != 200) {
                return Result.error(referenceResult.getCode(), "发送求购引用消息失败：" + referenceResult.getMessage());
            }

            // 4. 记录日志
            log.info("用户 {} 联系求购 {} 的发布者 {}, 消息: {}", userId, id, publisherId, message);

            return Result.success(conversationResult.getData(), "联系发布者成功");
        } catch (Exception e) {
            log.error("联系发布者失败", e);
            return Result.error(500, "联系发布者失败：" + e.getMessage());
        }
    }

    @Override
    public Result<org.springframework.data.domain.Page<PurchaseRequestVO>> getSchoolRequests(
            Long schoolId, Double minBudget, Double maxBudget, String category, Pageable pageable, Long currentUserId) {

        // 构建缓存Key，简化缓存标识符以便于删除
        String cacheKey = CACHE_PURCHASE_SCHOOL + schoolId;
        if (currentUserId != null) {
            cacheKey += ":user:" + currentUserId;
        }

        // 尝试从缓存获取
        Object cachedResult = redisTemplate.opsForValue().get(cacheKey);
        if (cachedResult != null) {
            try {
                // 将缓存的Map数据转换回Page对象
                java.util.Map<String, Object> pageData = (java.util.Map<String, Object>) cachedResult;
                java.util.List<PurchaseRequestVO> content = (java.util.List<PurchaseRequestVO>) pageData.get("content");
                long totalElements = ((Number) pageData.get("totalElements")).longValue();
                int number = ((Number) pageData.get("number")).intValue();
                int size = ((Number) pageData.get("size")).intValue();

                org.springframework.data.domain.Page<PurchaseRequestVO> pageResult = new PageImpl<>(
                        content, org.springframework.data.domain.PageRequest.of(number, size), totalElements);

                return Result.success(pageResult, "获取成功(缓存)");
            } catch (Exception e) {
                log.warn("缓存数据反序列化失败", e);
                // 缓存数据有问题，继续查询数据库
            }
        }

        LambdaQueryWrapper<PurchaseRequest> queryWrapper = new LambdaQueryWrapper<>();

        // 学校ID筛选
        queryWrapper.eq(PurchaseRequest::getSchoolId, schoolId);
        queryWrapper.eq(PurchaseRequest::getIsActive, 1); // 只查询有效记录

        // 价格区间筛选
        if (minBudget != null) {
            queryWrapper.ge(PurchaseRequest::getBudget, minBudget);
        }
        if (maxBudget != null) {
            queryWrapper.le(PurchaseRequest::getBudget, maxBudget);
        }

        // 分类筛选
        if (category != null && !category.trim().isEmpty()) {
            queryWrapper.eq(PurchaseRequest::getCategoryId, category);
        }

        // 按创建时间倒序排序
        queryWrapper.orderByDesc(PurchaseRequest::getCreateTime);

        // 设置分页
        Page<PurchaseRequest> mybatisPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(
                pageable.getPageNumber() + 1, // MyBatis-Plus分页从1开始
                pageable.getPageSize());

        // 执行查询
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<PurchaseRequest> requestPage = this.page(mybatisPage,
                queryWrapper);

        // 转换为VO
        List<PurchaseRequestVO> voList = new ArrayList<>();
        for (PurchaseRequest request : requestPage.getRecords()) {
            PurchaseRequestVO vo = convertToVO(request);

            // 如果提供了当前用户ID，检查该用户是否已收藏此求购信息
            if (currentUserId != null) {
                vo.setIsFavorite(favoriteService.isPurchaseRequestFavorite(currentUserId, request.getId()));
            } else {
                vo.setIsFavorite(false); // 默认为未收藏
            }

            voList.add(vo);
        }

        // 创建Spring Data的Page对象
        org.springframework.data.domain.Page<PurchaseRequestVO> resultPage = new PageImpl<>(
                voList, pageable, requestPage.getTotal());

        // 写入缓存
        java.util.Map<String, Object> pageData = new java.util.HashMap<>();
        pageData.put("content", voList);
        pageData.put("totalElements", requestPage.getTotal());
        pageData.put("number", pageable.getPageNumber());
        pageData.put("size", pageable.getPageSize());

        redisTemplate.opsForValue().set(cacheKey, pageData, 1, TimeUnit.HOURS);

        return Result.success(resultPage, "获取成功");
    }

    /**
     * 清除求购信息的所有缓存
     */
    private void clearPurchaseListCache() {
        log.info("清除求购信息列表缓存");
        redisTemplate.delete(CACHE_PURCHASE_LIST );
    }

    /**
     * 清除特定求购信息的缓存
     */
    private void clearPurchaseCache(Long purchaseId) {
        log.info("清除求购信息缓存: {}", purchaseId);
        redisTemplate.delete(CACHE_PURCHASE_DETAIL + purchaseId);
    }

    /**
     * 清除用户求购信息的缓存
     */
    private void clearUserPurchaseCache(Long userId) {
        log.info("清除用户求购信息缓存: {}", userId);
        redisTemplate.delete(CACHE_PURCHASE_USER + userId );
    }

    /**
     * 清除学校求购信息的缓存
     */
    private void clearSchoolPurchaseCache(Long schoolId) {
        log.info("清除学校求购信息缓存: {}", schoolId);
        redisTemplate.delete(CACHE_PURCHASE_SCHOOL + schoolId );
    }

    /**
     * 将PurchaseRequest转换为PurchaseRequestVO
     */
    private PurchaseRequestVO convertToVO(PurchaseRequest request) {
        PurchaseRequestVO vo = new PurchaseRequestVO();

        // 基本字段复制
        vo.setId(request.getId());
        vo.setTitle(request.getTitle());
        vo.setDescription(request.getDescription());
        vo.setBudget(request.getBudget());
        vo.setCategoryId(request.getCategoryId());
        vo.setContactInfo(request.getContactInfo());

        // 设置分类名称
        String categoryName = categoryService.getCategoryName(request.getCategoryId());
        vo.setCategoryName(categoryName);

        vo.setViews(request.getViews());

        // 设置格式化时间
        vo.setTime(formatTime(request.getCreateTime()));

        // 设置状态
        vo.setStatus(request.getStatus());

        vo.setCreateTime(request.getCreateTime());
        vo.setExpireTime(request.getExpireTime());

        // 设置用户信息
        User user = userService.getUserById(request.getUserId());
        if (user != null) {
            UserSimpleVO userVO = UserSimpleVO.builder()
                    .id(user.getId())
                    .name(user.getNickname())
                    .avatar(user.getAvatar())
                    .school(getSchoolName(user.getSchoolId()))
                    .build();
            vo.setUser(userVO);
        }

        return vo;
    }

    /**
     * 将PurchaseRequest转换为PurchaseRequestDetailVO
     */
    private PurchaseRequestDetailVO convertToDetailVO(PurchaseRequest request) {
        PurchaseRequestDetailVO vo = new PurchaseRequestDetailVO();

        // 基本字段复制
        vo.setId(request.getId());
        vo.setTitle(request.getTitle());
        vo.setDescription(request.getDescription());
        vo.setBudget(request.getBudget());
        vo.setCategoryId(request.getCategoryId());

        // 设置分类名称
        String categoryName = categoryService.getCategoryName(request.getCategoryId());
        vo.setCategoryName(categoryName);

        vo.setViews(request.getViews());
        vo.setCreateTime(request.getCreateTime());
        vo.setUpdateTime(request.getUpdateTime());
        // 设置状态
        vo.setStatus(request.getStatus());

        // 设置格式化时间
        vo.setFormatTime(formatTime(request.getCreateTime()));

        // 设置用户信息
        User user = userService.getUserById(request.getUserId());
        if (user != null) {
            UserDetailVO userVO = UserDetailVO.builder()
                    .id(user.getId())
                    .name(user.getNickname())
                    .avatar(user.getAvatar())
                    .school(getSchoolName(user.getSchoolId()))
                    .credibility(user.getCredibility())
                    .build();
            vo.setUser(userVO);
        }

        return vo;
    }

    /**
     * 格式化时间为"几分钟前"、"几小时前"等格式
     */
    private String formatTime(LocalDateTime time) {
        if (time == null) {
            return "";
        }

        LocalDateTime now = LocalDateTime.now();
        long minutes = ChronoUnit.MINUTES.between(time, now);

        if (minutes < 1) {
            return "刚刚";
        } else if (minutes < 60) {
            return minutes + "分钟前";
        } else if (minutes < 24 * 60) {
            return (minutes / 60) + "小时前";
        } else if (minutes < 30 * 24 * 60) {
            return (minutes / (24 * 60)) + "天前";
        } else if (minutes < 12 * 30 * 24 * 60) {
            return (minutes / (30 * 24 * 60)) + "个月前";
        } else {
            return (minutes / (12 * 30 * 24 * 60)) + "年前";
        }
    }

    /**
     * 根据学校ID获取学校名称
     */
    private String getSchoolName(Long schoolId) {
        return schoolService.getSchoolById(schoolId)
                .getData()
                .getName();
    }
}